/*
 * main.cpp
 *
 *  Created on: May 14, 2010
 *      Author: z1083248
 */
#include "config.hpp"
#include "fft_basic.hpp"
#include "image_app.hpp"
#include "fft_ops.hpp"
#include <cstring>
#include <string>
#include <iostream>
#include <complex>

using namespace std;
using namespace FftLib::Basic;
using namespace TestAppFftLib;

void printErrorUsage()
{
   cout << endl << endl;
   cout << "Usage: test_app_fft_lib -f1 <path_to_image_1> ";
   cout << "-f2 <path_to_image_2> <options>";
   cout << endl << endl;
   cout << " options:" << endl;
   cout << "   -d <directory_to_place_output>";
   cout << endl << endl;
}

void testBed()
{
   //
   // Test Matrix swap algorithm
   //
   float matrix4[16] =
   { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
   float matrix3[9] =
   { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
   complex<float> complexMatrix8[8];

   cout << "4x4 Matrix - original:" << endl;
   for (int row = 0; row < 4; ++row)
   {
      for (int col = 0; col < 4; ++col)
      {
         cout << matrix4[col + (row * 4)] << ",";
      }
      cout << endl;
   }

   squareMatrixTranspose(matrix4, 4);

   cout << "4x4 Matrix - transpose:" << endl;
   for (int row = 0; row < 4; ++row)
   {
      for (int col = 0; col < 4; ++col)
      {
         cout << matrix4[col + (row * 4)] << ",";
      }
      cout << endl;
   }
   cout << endl;

   squareMatrixTranspose(matrix4, 4);

   cout << "4x4 Matrix - transpose again:" << endl;
   for (int row = 0; row < 4; ++row)
   {
      for (int col = 0; col < 4; ++col)
      {
         cout << matrix4[col + (row * 4)] << ",";
      }
      cout << endl;
   }
   cout << endl;

   convertDataToComplex(matrix4, complexMatrix8, 16);

   cout << "complex vector of length 8:" << endl;
   for (int index = 0; index < 8; ++index)
   {
      cout << complexMatrix8[index] << endl;
   }
   cout << endl;

   convertComplexToData(complexMatrix8, matrix4, 16);

   cout << "2x2 Matrix - From Complex:" << endl;
   for (int row = 0; row < 4; ++row)
   {
      for (int col = 0; col < 4; ++col)
      {
         cout << matrix4[col + (row * 4)] << ",";
      }
      cout << endl;
   }
   cout << endl;

   cout << "3x3 Matrix - original:" << endl;
   for (int row = 0; row < 3; ++row)
   {
      for (int col = 0; col < 3; ++col)
      {
         cout << matrix3[col + (row * 3)] << ",";
      }
      cout << endl;
   }
   cout << endl;

   squareMatrixTranspose(matrix3, 3);

   cout << "3x3 Matrix - reverse:" << endl;
   for (int row = 0; row < 3; ++row)
   {
      for (int col = 0; col < 3; ++col)
      {
         cout << matrix3[col + (row * 3)] << ",";
      }
      cout << endl;
   }
   cout << endl;
}

int main(int argc, char *argv[])
{
   //testBed();
   static const int maxArg = 7;
   static const int minArg = 5;
   ImageApp imageApp;

   if (argc < minArg || argc > maxArg)
   {
      printErrorUsage();
      return -1;
   }

   for (int index = 1; index < argc; index += 2)
   {
      if (strcmp(argv[index], "-f1") == 0)
      {
         imageApp.loadImage(TestAppFftLib::ImageOne, argv[index + 1]);
      }
      else if (strcmp(argv[index], "-f2") == 0)
      {
         imageApp.loadImage(TestAppFftLib::ImageTwo, argv[index + 1]);
      }
      else if (strcmp(argv[index], "-d") == 0)
      {
         imageApp.setImageDirectory(argv[index + 1]);
      }
      else
      {
         cout << endl << "Unrecognized Input detected." << endl;
         printErrorUsage();
         return -1;
      }
   }

   if (!imageApp.getAllImagesLoaded())
   {
      cout << endl << "Not all images were loaded correctly." << endl;
      printErrorUsage();
      return -1;
   }

   //imageApp.writeImageSourceData();

   imageApp.executeBasicFft();
   imageApp.writeData(ImageApp::BasicFftDataName);

   imageApp.executeBasicReduxFft();
   imageApp.writeData(ImageApp::BasicReduxFftDataName);

   imageApp.executeBasicReduxComplexFft();
   imageApp.writeData(ImageApp::BasicReduxFftComplexDataName);

   imageApp.executeRadix2Fft();
   imageApp.writeData(ImageApp::BasicRadix2DataName);

   imageApp.executeFftw();
   imageApp.writeData(ImageApp::FftwDataName);

   return 0;
}
